/*
 *	IncomeStatementCSVParser.cpp
 *
 * 	Copyright (C) 2011 Aaron Huang
 * 	This file is part of StackPainter.
 *
 * 	StackPainter is free software: you can redistribute it and/or modify
 * 	it under the terms of the GNU General Public License as published by
 * 	the Free Software Foundation, either version 3 of the License, or
 * 	(at your option) any later version.
 *
 * 	StackPainter is distributed in the hope that it will be useful,
 * 	but WITHOUT ANY WARRANTY; without even the implied warranty of
 * 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * 	GNU General Public License for more details.
 *
 * 	You should have received a copy of the GNU General Public License
 * 	along with StackPainter.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "IncomeStatementCSVParser.h"
#include "CompanyInfo.h"

#include <QDir>
#include <QRegExp>
#include <QByteArray>
#include <QTextCodec>
#include <QStringList>

const QString FILE_LOCALE   = "big5";
const QString DATA_DIR 		= "Data";
const QString SEPERATOR		= ",";
const QString COMPANY_NUM	= "\"公司代號\"";
const QString COMPANY_NAME	= "\"公司名稱\"";
const QRegExp COMPANY_EPS(QString("*每股*"), Qt::CaseInsensitive, QRegExp::Wildcard);
const QString EMPTY_DIR = "The selected directory is empty!";
const QString FILE_FORMAT_ERROR = "The file format is error!";

IncomeStatementCSVParser::IncomeStatementCSVParser() : _dirPath("") {}

IncomeStatementCSVParser::~IncomeStatementCSVParser() {}

void IncomeStatementCSVParser::setDirPath(QString path) {
	_dirPath = path;
}

QList<CompanyInfo*> IncomeStatementCSVParser::parse() throw(QString) {
	QFileInfoList fileInfos = getFileInfosByPath();
	_companyInfos.clear();
	foreach (const QFileInfo& fileInfo, fileInfos) {
		parseFile(fileInfo.baseName().toInt(), fileInfo.filePath());
	}
	return _companyInfos.values();
}

QFileInfoList IncomeStatementCSVParser::getFileInfosByPath() throw(QString) {
	QDir dir(_dirPath);
	QFileInfoList fileInfos = dir.entryInfoList(QDir::Files, QDir::Name);
	if (fileInfos.isEmpty()) {
		throw EMPTY_DIR;
	}
	return fileInfos;
}

void IncomeStatementCSVParser::readLine(QFile& file, QString& aLine) {
	QByteArray lineByteArray = file.readLine();
	QTextCodec* codec = QTextCodec::codecForName(FILE_LOCALE.toUtf8());
	aLine = codec->toUnicode(lineByteArray);
	codec = QTextCodec::codecForLocale();
	aLine = codec->fromUnicode(aLine);
}

void IncomeStatementCSVParser::findFieldMap(QFile& file) throw(QString) {
	QString aLine;
	readLine(file, aLine);
	QStringList items = aLine.split(SEPERATOR);
	int numIndex = items.indexOf(COMPANY_NUM);
	int nameIndex = items.indexOf(COMPANY_NAME);
	int EPSIndex = items.indexOf(COMPANY_EPS);
	if (numIndex == -1 || nameIndex == -1 || EPSIndex == -1) {
		file.close();
		throw FILE_FORMAT_ERROR;
	}
	_fieldsMap.insert("num", numIndex);
	_fieldsMap.insert("name", nameIndex);
	_fieldsMap.insert("EPS", EPSIndex);
}

void IncomeStatementCSVParser::parseItems(int year, QFile& file) {
	QString aLine;
	readLine(file, aLine);
	QStringList items = aLine.split(SEPERATOR);
	int numField = _fieldsMap.value("num");
	int nameField = _fieldsMap.value("name");
	int EPSField = _fieldsMap.value("EPS");
	QString numStr = items.at(numField);
	numStr = numStr.remove('\"');
	int num = numStr.toInt();
	QString name = items.at(nameField);
	name = name.remove('\"');
	double EPS = items.at(EPSField).toDouble();
	QMap<int, CompanyInfo*>::Iterator companyIt = _companyInfos.find(num);
	if (companyIt == _companyInfos.end()) {
		_companyInfos.insert(num, new CompanyInfo(num, name, year, EPS));
	}
	else {
		companyIt.value()->addEPS(year, EPS);
	}
}

void IncomeStatementCSVParser::parseFile(int year, const QString& fileName) {
	_fieldsMap.clear();
	QFile file(fileName);
	file.open(QIODevice::ReadOnly);
	findFieldMap(file);
	while (!file.atEnd()) {
		parseItems(year, file);
	}
	file.close();
}
